Update plugin ZTools 提供商 v1.0.1#307
Conversation
- feat: ZTools OCR + 翻译提供商插件(截图识别 / 代码翻译 / manage) - chore: 调整插件命名空间 - chore: 调整资源url - feat: 微信 OCR 原生模块支持 macOS(libwxocr.dylib) - feat: 截图识别结果改为独立窗口展示(左图右文 + 拖动缩放)
There was a problem hiding this comment.
Code Review
This pull request refactors the screenshot OCR feature by moving the results display into a separate, borderless child window (ScreenOcrResult.vue), while the main window (ScreenOcr.vue) acts as an orchestrator that captures the screen, runs the OCR, and injects the results. Feedback suggests adding defensive checks when retrieving display information to prevent potential crashes, handling the asynchronous promise rejection of the clipboard API, and removing a redundant, unused helper function in the results view.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const display = window.ztools.getPrimaryDisplay() | ||
| // workArea 同为 DIP,含任务栏扣除,比 size 更安全 | ||
| const workArea = display.workArea | ||
| const screenWDip = workArea.width | ||
| const screenHDip = workArea.height | ||
| // scaleFactor:如 1 / 1.25 / 1.5 / 1.9 / 2 | ||
| const scaleFactor = display.scaleFactor || 1 |
There was a problem hiding this comment.
在获取主显示器信息时,window.ztools.getPrimaryDisplay() 可能会返回 undefined(例如在某些异常情况或测试环境中)。直接访问 display.workArea 会导致 TypeError 崩溃。建议使用可选链(optional chaining)进行防御性保护,并提供合理的默认值。
const display = window.ztools.getPrimaryDisplay()
// workArea 同为 DIP,含任务栏扣除,比 size 更安全
const workArea = display?.workArea || { x: 0, y: 0, width: 1280, height: 800 }
const screenWDip = workArea.width
const screenHDip = workArea.height
// scaleFactor:如 1 / 1.25 / 1.5 / 1.9 / 2
const scaleFactor = display?.scaleFactor || 1
| function copyText(text: string) { | ||
| if (!text) return | ||
| try { | ||
| navigator.clipboard?.writeText(text) | ||
| } catch (_) { | ||
| /* 子窗口可能无 clipboard 权限,静默失败 */ | ||
| } |
There was a problem hiding this comment.
由于 navigator.clipboard.writeText 是一个异步操作并返回一个 Promise,如果复制失败(例如子窗口没有剪贴板权限,或者文档未聚焦),它会抛出异步拒绝(Promise Rejection)。传统的同步 try-catch 块无法捕获异步的 Promise Rejection,这会导致控制台出现 "Unhandled Promise Rejection" 警告。建议使用 .catch() 显式捕获并处理该 Promise。
function copyText(text: string) {
if (!text) return
navigator.clipboard?.writeText(text)?.catch(() => {
/* 子窗口可能无 clipboard 权限,静默失败 */
})
| const el = list.children[i] as HTMLElement | undefined | ||
| if (el) { | ||
| el.scrollIntoView({ block: 'nearest', behavior: 'smooth' }) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * 点击图上文字:若是拖动结束(didDrag)则不触发,避免拖图误复制; | ||
| * 否则复制该行文字并闪烁高亮反馈。 | ||
| */ | ||
| function onOverlayClick(i: number): void { | ||
| if (didDrag) { | ||
| didDrag = false | ||
| return | ||
| } | ||
| flashLine(i) | ||
| copyText(lines.value[i]?.text ?? '') | ||
| } | ||
|
|
||
| /** 触发第 i 行的闪烁高亮(图上 + 列表),1.5s 后移除。 */ | ||
| function flashLine(i: number): void { | ||
| activeIndex.value = i | ||
| const id = (flashedIds.value[i] ?? 0) + 1 | ||
| flashedIds.value[i] = id | ||
| window.setTimeout(() => { | ||
| if (flashedIds.value[i] === id) flashedIds.value[i] = 0 |
插件信息
本次变更
截图 / 演示
自检清单
plugins/f-provider/目录此 PR 由 ztools-plugin-cli 自动管理:每次
ztools publish在分支上追加一个 commit,PR 链接保持不变。